package vg.services.graph_view_manager.realization.graph_view.smart_graph_view.realization;

import java.util.ArrayDeque;
import java.util.Queue;

import vg.services.graph_view_manager.realization.graph_view.smart_graph_view.interfaces.ISGVGraphView4Patching;
import vg.services.graph_view_manager.realization.graph_view.smart_graph_view.interfaces.ISGVPatch;
import vg.services.graph_view_manager.realization.graph_view.smart_graph_view.interfaces.ISGVTopScreen;
import vg.services.graph_view_manager.realization.graph_view.smart_graph_view.interfaces.ISGVPatchManager;
import vg.services.main_manager.MainManager;

public class SGVPatchManager implements ISGVPatchManager {
	// Main data
	private ISGVTopScreen topScreen = null;
	
	// Main components 
	private Queue<ISGVPatch> patches = null;
	private int currentPatchId = 0;
	private int currentCompletePatchId = -1;
	
	// Mutex
	private final Object generalMutex = new Object();
	
	/**
	 * Constructor
	 */
	public SGVPatchManager(ISGVTopScreen topScreen) {
		this.topScreen = topScreen;
		
		patches = new ArrayDeque<ISGVPatch>();
		
		init_thread();
	}
	
	@Override
	public int addPatch(ISGVPatch patch) {
		synchronized (generalMutex) {
			patches.add(patch);
			return currentPatchId++;
		}
	}
	
	@Override
	public boolean isComplete(int patchId) {
		synchronized (generalMutex) {
			if (patchId <= currentCompletePatchId)
				return true;
			return false;
		}
	}
	
//=============================================================================
//-----------------PRIVATE METHODS---------------------------------------------
	private void init_thread() {
		// start thread
		Thread t = new Thread(new Runnable() {			
			@Override
			public void run() {
				// TODO FIX ME
				while (true) {
					ISGVPatch patch = null;
					synchronized(generalMutex) {
						if (!patches.isEmpty()) {
							patch = patches.poll();
						}
					}
					
					if (patch == null) {
						try {
							Thread.sleep(100);
						} catch (Exception ex) {}
					} else {
						apply_patch(patch);
					}
				}
			}
		});
		t.setDaemon(true);
		t.start();
	}
	
	private void apply_patch(ISGVPatch patch) {
		try {
			ISGVGraphView4Patching graphView4patching = null;
			// lock
			while (graphView4patching == null) {
				graphView4patching = topScreen.lock(patch.getProgressTask());
				if (graphView4patching == null) {
					try {
						Thread.sleep(100);
					} catch (Exception ex) {}
				}
			}
			
			// execute
			patch.apply(graphView4patching);
			
			// unlock
			topScreen.unlock();
			
			// update tasks
			currentCompletePatchId++;
		} catch (Throwable ex) {
			MainManager.log.printException(ex);
		}
	}
}
